#
#    Copyright (C) 2016 Francisco Javier Parra <franparpe@openmailbox.org>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
#

import numpy
from qtcam.core.parameters import SectionParameters
import math


class ModifiedSinusoidalSection(SectionParameters):
    """This class represents the modified cicloidal section
which is used to reduce the maximun value of the acceleration. This
is achieved by combining sinoidal expresions with diferent frequency
    
    """
    def __init__(self, LowestPosition=0.0,
                 HighestPosition=50.0, StartAngle=0.0,
                 EndAngle=100.0, Precision=0.1, AngularVelocity=1):
        super(ModifiedSinusoidalSection, self).__init__(LowestPosition,
                                                        HighestPosition,
                                                        StartAngle,
                                                        EndAngle,
                                                        Precision,
                                                        AngularVelocity)

    def ArrayPosition(self):
        """Returns the values that corresponds to the position
        
        """
        beta = self.EndAngle - self.StartAngle
        theta_array = self.abcissaeValues - self.StartAngle
        result = numpy.array([])

        for theta in theta_array:
            if 0 <= (theta / beta) < (1/8):
                s = self.LowestPosition + (self.HighestPosition *
                                           (0.43990085 * (theta / beta) -
                                            0.0350062 * numpy.sin((4 *
                                                                   numpy.pi *
                                                                   theta) /
                                                                  beta)))
                result = numpy.append(result, s)
            if (1/8) <= (theta / beta) < (7/8):
                s = self.LowestPosition + (self.HighestPosition *
                                           (0.2804957 +
                                            0.43990085 * (theta / beta) -
                                            0.31505577 *
                                            numpy.cos(((4 * numpy.pi * theta) /
                                                       (3 * beta)) -
                                                      (numpy.pi / 6))))
                result = numpy.append(result, s)
            if (7/8) <= (theta / beta) < 1:
                s = self.LowestPosition + (self.HighestPosition *
                                           (0.56009915 +
                                            0.43990085 * (theta / beta) -
                                            0.0350062 *
                                            numpy.sin(2 * numpy.pi *
                                                      (((2 * theta) /
                                                        beta) - 1))))
                result = numpy.append(result, s)

        return result

    def ArrayVelocity(self):
        """This returns the velocity of the cam
        
        """
        beta = self.EndAngle - self.StartAngle
        theta_array = self.abcissaeValues - self.StartAngle
        result = numpy.array([])

        for theta in theta_array:
            if 0 <= (theta / beta) < (1/8):
                v = (self.AngularVelocity *
                     0.43990085 *
                     (self.HighestPosition / math.radians(beta)) *
                     (1 - numpy.cos((4 *
                                     numpy.pi *
                                     theta) /
                                    beta)))
                result = numpy.append(result, v)
            if (1/8) <= (theta / beta) < (7/8):
                v = (self.AngularVelocity *
                     0.43990085 *
                     (self.HighestPosition / math.radians(beta)) *
                     (1 + 3 * numpy.sin(((4 * numpy.pi * theta) /
                                         (3 * beta)) -
                                        (numpy.pi / 6))))
                     
                result = numpy.append(result, v)
            if (7/8) <= (theta / beta) < 1:
                v = (self.AngularVelocity *
                     0.43990085 *
                     (self.HighestPosition / math.radians(beta)) *
                     (1 - numpy.cos(2 * numpy.pi *
                                    (((2 * theta) /
                                      beta) - 1))))

                result = numpy.append(result, v)

        return result

    def ArrayAcceleration(self):
        """This returns the acceleration of the cam in an array
        
        """
        beta = self.EndAngle - self.StartAngle
        theta_array = self.abcissaeValues - self.StartAngle
        result = numpy.array([])

        for theta in theta_array:
            if 0 <= (theta / beta) < (1/8):
                a = (numpy.power(self.AngularVelocity, 2) *
                     5.5279571 *
                     (self.HighestPosition / numpy.power(math.radians(beta), 2)) *
                     (numpy.sin((4 *
                                 numpy.pi *
                                 theta) /
                                beta)))
                result = numpy.append(result, a)
            if (1/8) <= (theta / beta) < (7/8):
                a = (numpy.power(self.AngularVelocity, 2) *
                     5.5279571 *
                     (self.HighestPosition / numpy.power(math.radians(beta), 2)) *
                     (numpy.cos(((4 * numpy.pi * theta) /
                                 (3 * beta)) -
                                (numpy.pi / 6))))
                     
                result = numpy.append(result, a)
            if (7/8) <= (theta / beta) < 1:
                a = (numpy.power(self.AngularVelocity, 2) *
                     5.5279571 *
                     (self.HighestPosition / numpy.power(math.radians(beta), 2)) *
                     (numpy.sin(2 * numpy.pi *
                                (((2 * theta) /
                                  beta) - 1))))

                result = numpy.append(result, a)

        return result

    def ArrayOverAcceleration(self):
        """This returns the acceleration of the cam in an array
        
        """
        beta = self.EndAngle - self.StartAngle
        theta_array = self.abcissaeValues - self.StartAngle
        result = numpy.array([])

        for theta in theta_array:
            if 0 <= (theta / beta) < (1/8):
                j = (numpy.power(self.AngularVelocity, 3) *
                     69.4663577 *
                     (self.HighestPosition / numpy.power(math.radians(beta), 3)) *
                     (numpy.cos((4 *
                                 numpy.pi *
                                 theta) /
                                beta)))
                result = numpy.append(result, j)
            if (1/8) <= (theta / beta) < (7/8):
                j = -(numpy.power(self.AngularVelocity, 3) *
                      23.1553 *
                      (self.HighestPosition / numpy.power(math.radians(beta), 3)) *
                      (numpy.sin(((4 * numpy.pi * theta) /
                                  (3 * beta)) -
                                 (numpy.pi / 6))))
                     
                result = numpy.append(result, j)
            if (7/8) <= (theta / beta) < 1:
                j = (numpy.power(self.AngularVelocity, 3) *
                     69.4663577 *
                     (self.HighestPosition / numpy.power(math.radians(beta), 3)) *
                     (numpy.cos(2 * numpy.pi *
                                (((2 * theta) /
                                  beta) - 1))))

                result = numpy.append(result, j)

        return result
